#include "Stdafx.h"
#include "R09CPU.h"

R09CPU::R09CPU(RAM^ ramHandle)
{
	running = false;

	registers = gcnew R09RegisterSet();
	callStack = gcnew CallStack(ramHandle, 128);
	ram = ramHandle;
}

Boolean R09CPU::LoadDataToMemory(array<UInt32>^ dataHandle, UInt32 startAddress)
{
	return ram->LoadIntoMemory(dataHandle, startAddress);
}

Boolean R09CPU::LoadProgramToStack(array<UInt32>^ programHandle, Boolean jumpToAddress)
{
	if (jumpToAddress)
	{
		PC = SP;
	}

	return callStack->LoadDataArray(programHandle, SP);
}

Boolean R09CPU::StartCPU(UInt32 startAddress)
{
	if (ram->RamSize < 128)
	{
		return false;
	}

	PC = startAddress;

	task = gcnew Task(gcnew Action(this, &VirtualHardware::R09CPU::TaskFunction));
	task->Start();

	return true;
}

void R09CPU::TaskFunction()
{
	while (running)
	{
		Fetch();
		Execute();
	}
}

void R09CPU::Fetch()
{
	MAR = PC;
	PC += 4;
	MDR = callStack[MAR];
	IR = MDR;
}

void R09CPU::Execute()
{
	switch (OPCODE)
	{
		case 0:  ADD  break;
		case 1:  ADDL break;
		case 2:  SUB  break;
		case 3:  SUBL break;
		case 4:  MUL  break;
		case 5:  DIV  break;
		case 6:  LDDW  break;
		case 7:  LDW break;
		case 8:  LDB  break;
		case 9:  LDL  break;
		case 10: STDW  break;
		case 11: STB  break;
		case 12: MFH  break;
		case 13: MFL  break;
		case 14: AND  break;
		case 15: ANDL break;
		case 16: OR   break;
		case 17: ORL  break;
		case 18: XOR  break;
		case 19: NOR  break;
		case 20: NOT  break;
		case 21: SLT  break;
		case 22: SLTL break;
		case 23: SL   break;
		case 24: SR   break;
		case 25: BEQ  break;
		case 26: BNE  break;
		case 27: BGT  break;
		case 28: BLT  break;
		case 29: BGE  break;
		case 30: BLE  break;
		case 31: JMP  break;
		case 32: JMPR break;
		case 33: JAL  break;
		case 34: JALR break;
		case 35: RET  break;
		case 36: MOV  break;
		case 37: CLR  break;
		case 38: PUSH break;
		case 39: POP  break;
	}
}
